home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / bash / bash_108 / bash-108.zoo / src / bashline.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-09-12  |  32.0 KB  |  1,291 lines

  1. /* bashline.c -- Bash's interface to the readline library. */
  2.  
  3. /* Copyright (C) 1987,1991 Free Software Foundation, Inc.
  4.  
  5.    This file is part of GNU Bash, the Bourne Again SHell.
  6.  
  7.    Bash is free software; you can redistribute it and/or modify it
  8.    under the terms of the GNU General Public License as published by
  9.    the Free Software Foundation; either version 1, or (at your option)
  10.    any later version.
  11.  
  12.    Bash is distributed in the hope that it will be useful, but WITHOUT
  13.    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  14.    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
  15.    License for more details.
  16.  
  17.    You should have received a copy of the GNU General Public License
  18.    along with Bash; see the file COPYING.  If not, write to the Free
  19.    Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  20.  
  21. #include <stdio.h>
  22. #include <readline/readline.h>
  23. #include <readline/history.h>
  24. #include "shell.h"
  25. #include "builtins.h"
  26.  
  27. /* Functions bound to keys in Readline for Bash users. */
  28. static void
  29.   shell_expand_line (), insert_last_arg (), display_shell_version (),
  30.   operate_and_get_next ();
  31.  
  32. /* Helper functions for Readline. */
  33. static void
  34.   bash_symbolic_link_hook (), filename_completion_ignore (), bash_push_line ();
  35.  
  36. static char
  37.   **attempt_shell_completion (), *bash_tilde_expand (),
  38.   *variable_completion_function (), 
  39.  
  40. /**
  41.  ** (sjk)++ Remove hostname/mail references on the Atari ST.
  42.  **/
  43. #if !defined(atarist)
  44. *hostname_completion_function (),
  45. #endif
  46.   *command_word_completion_function ();
  47.  
  48. /**
  49.  ** (sjk)++ Remove hostname/mail references on the Atari ST.
  50.  **/
  51. #if !defined(atarist)
  52. static void
  53.   snarf_hosts_from_file (), add_host_name (), sort_hostname_list ();
  54. #endif 
  55.  
  56. /* Externally defined functions used by this file. */
  57. extern char
  58.   *get_string_value (), *filename_completion_function (),
  59.   *username_completion_function ();
  60.  
  61. extern int
  62.   show_shell_version ();
  63.  
  64. /* SPECIFIC_COMPLETION_FUNCTIONS specifies that we have individual
  65.    completion functions which indicate what type of completion should be
  66.    done (at or before point) that can be bound to key sequences with
  67.    the readline library. */
  68. #define SPECIFIC_COMPLETION_FUNCTIONS
  69.  
  70. #if defined (SPECIFIC_COMPLETION_FUNCTIONS)
  71. static void
  72.   bash_specific_completion (),
  73.   bash_complete_filename (), bash_possible_filename_completions (),
  74.   bash_complete_filename_internal (),
  75.   bash_complete_username (), bash_possible_username_completions (),
  76.   bash_complete_username_internal (),
  77. /**
  78.  ** (sjk)++ Remove hostname/mail references on the Atari ST.
  79.  **/
  80. #if !defined(atarist)
  81.   bash_complete_hostname (), bash_possible_hostname_completions (),
  82.   bash_complete_hostname_internal (),
  83. #endif 
  84.   bash_complete_variable (), bash_possible_variable_completions (),
  85.   bash_complete_variable_internal (),
  86.   bash_complete_command (), bash_possible_command_completions (),
  87.   bash_complete_command_internal ();
  88. #endif /* SPECIFIC_COMPLETION_FUNCTIONS */
  89.  
  90. /* Called once from parse.y if we are going to use readline. */
  91. initialize_readline ()
  92. {
  93.   rl_terminal_name = get_string_value ("TERM");
  94.   rl_instream = stdin, rl_outstream = stderr;
  95.   rl_special_prefixes = "$@%";
  96.  
  97.   /* Allow conditional parsing of the ~/.inputrc file. */
  98.   rl_readline_name = "Bash";
  99.  
  100.   /* Bind up our special shell functions. */
  101.   rl_add_defun
  102.     ("shell-expand-line", (Function *)shell_expand_line, META(CTRL('E')));
  103.  
  104.   rl_add_defun
  105.     ("insert-last-argument", (Function *)insert_last_arg, META('.'));
  106.  
  107.   rl_bind_key (META('_'), (Function *)insert_last_arg);
  108.  
  109.   rl_add_defun
  110.     ("operate_and_get_next", (Function *)operate_and_get_next, CTRL('O'));
  111.  
  112.   rl_add_defun
  113.     ("display-shell-version", (Function *)display_shell_version, -1);
  114.  
  115.   rl_bind_key_in_map
  116.     (CTRL ('V'), (Function *)display_shell_version, emacs_ctlx_keymap);
  117.  
  118.   /* In Bash, the user can switch editing modes with "set -o [vi emacs]",
  119.      so it is not necessary to allow C-M-j for context switching.  Turn
  120.      off this occasionally confusing behaviour. */
  121.   rl_unbind_key_in_map (CTRL('J'), emacs_meta_keymap);
  122.  
  123. #ifdef SPECIFIC_COMPLETION_FUNCTIONS
  124.   rl_add_defun ("complete-filename", bash_complete_filename, META('/'));
  125.   rl_add_defun ("possible-filename-completions",
  126.         bash_possible_filename_completions, -1);
  127.   rl_bind_key_in_map ('/', bash_possible_filename_completions,
  128.               emacs_ctlx_keymap);
  129.  
  130.   rl_add_defun ("complete-username", bash_complete_username, META('~'));
  131.   rl_add_defun ("possible-username-completions",
  132.         bash_possible_username_completions, -1);
  133.   rl_bind_key_in_map ('~', bash_possible_username_completions,
  134.               emacs_ctlx_keymap);
  135.  
  136. /**
  137.  ** (sjk)++ Remove hostname/mail references on the Atari ST.
  138.  **/
  139. #if !defined(atarist)
  140.   rl_add_defun ("complete-hostname", bash_complete_hostname, META('@'));
  141.   rl_add_defun ("possible-hostname-completions",
  142.         bash_possible_hostname_completions, -1);
  143.   rl_bind_key_in_map ('@', bash_possible_hostname_completions,
  144.               emacs_ctlx_keymap);
  145. #endif 
  146.  
  147.   rl_add_defun ("complete-variable", bash_complete_variable, META('$'));
  148.   rl_add_defun ("possible-variable-completions",
  149.         bash_possible_variable_completions, -1);
  150.   rl_bind_key_in_map ('$', bash_possible_variable_completions,
  151.               emacs_ctlx_keymap);
  152.  
  153.   rl_add_defun ("complete-command", bash_complete_command, META('!'));
  154.   rl_add_defun ("possible-command-completions",
  155.         bash_possible_command_completions, -1);
  156.   rl_bind_key_in_map ('!', bash_possible_command_completions,
  157.               emacs_ctlx_keymap);
  158.  
  159. #endif  /* SPECIFIC_COMPLETION_FUNCTIONS */
  160.  
  161.   /* Tell the completer that we want a crack first. */
  162.   rl_attempted_completion_function = (Function *)attempt_shell_completion;
  163.  
  164.   /* Tell the tilde expander that we want a crack if it fails. */
  165.   rl_tilde_expander = (Function *)bash_tilde_expand;
  166.  
  167.   /* Tell the completer that we might want to follow symbolic links. */
  168.   rl_symbolic_link_hook = (Function *)bash_symbolic_link_hook;
  169.  
  170.   /* Tell the filename completer we want a chance to ignore some names. */
  171.   rl_ignore_some_completions_function =
  172.     (Function *)filename_completion_ignore;
  173. }
  174.  
  175. /* On Sun systems at least, rl_attempted_completion_function can end up
  176.    getting set to NULL, and rl_completion_entry_function set to do command
  177.    word completion if Bash is interrupted while trying to complete a command
  178.    word.  This just resets all the completion functions to the right thing.
  179.    It's called from throw_to_top_level(). */
  180. bashline_reinitialize ()
  181. {
  182.   rl_attempted_completion_function = (Function *)attempt_shell_completion;
  183.   rl_tilde_expander = (Function *)bash_tilde_expand;
  184.   rl_symbolic_link_hook = (Function *)bash_symbolic_link_hook;
  185. }
  186.  
  187. /* Contains the line to push into readline. */
  188. static char *push_to_readline = (char *)NULL;
  189.  
  190. /* Push the contents of push_to_readline into the
  191.    readline buffer. */
  192. static void
  193. bash_push_line ()
  194. {
  195.   if (push_to_readline)
  196.     {
  197.       rl_insert_text (push_to_readline);
  198.       free (push_to_readline);
  199.       push_to_readline = (char *)NULL;
  200.     }
  201. }
  202.  
  203. /* Call this to set the initial text for the next line to read
  204.    from readline. */
  205. int
  206. bash_re_edit (line)
  207.      char *line;
  208. {
  209.   if (push_to_readline)
  210.     free (push_to_readline);
  211.  
  212.   push_to_readline = savestring (line);
  213.   rl_startup_hook = (Function *)bash_push_line;
  214.  
  215.   return (0);
  216. }
  217.  
  218. static void
  219. display_shell_version (count, c)
  220.      int count, c;
  221. {
  222.   crlf ();
  223.   show_shell_version ();
  224.   putc ('\r', rl_outstream);
  225.   fflush (rl_outstream);
  226.   rl_on_new_line ();
  227.   rl_redisplay ();
  228. }
  229.  
  230. /* **************************************************************** */
  231. /*                                    */
  232. /*                 Readline Stuff                */
  233. /*                                    */
  234. /* **************************************************************** */
  235.  
  236. /**
  237.  ** (sjk)++ Remove hostname/mail references on the Atari ST.
  238.  **/
  239. #if !defined(atarist)
  240. /* If the user requests hostname completion, then simply build a list
  241.    of hosts, and complete from that forever more. */
  242. #if !defined (ETCHOSTS)
  243. #define ETCHOSTS "/etc/hosts"
  244. #endif
  245.  
  246. /* The kept list of hostnames. */
  247. static char **hostname_list = (char **)NULL;
  248.  
  249. /* The physical size of the above list. */
  250. static int hostname_list_size = 0;
  251.  
  252. /* The length of the above list. */
  253. static int hostname_list_length = 0;
  254.  
  255. /* Whether or not HOSTNAME_LIST has been initialized. */
  256. int hostname_list_initialized = 0;
  257.  
  258. /* Non-zero means that HOSTNAME_LIST needs to be sorted. */
  259. static int hostname_list_needs_sorting = 0;
  260.  
  261. /* Initialize the hostname completion table. */
  262. static void
  263. initialize_hostname_list ()
  264. {
  265.   char *temp = get_string_value ("hostname_completion_file");
  266.  
  267.   if (!temp)
  268.     temp = ETCHOSTS;
  269.  
  270.   snarf_hosts_from_file (temp);
  271.   sort_hostname_list ();
  272.   if (hostname_list)
  273.     hostname_list_initialized++;
  274. }
  275.  
  276. /* Add NAME to the list of hosts. */
  277. static void
  278. add_host_name (name)
  279.      char *name;
  280. {
  281.   if (hostname_list_length + 2 > hostname_list_size)
  282.     {
  283.       hostname_list = (char **)
  284.     xrealloc ((char *)hostname_list,
  285.           (1 + (hostname_list_size += 100)) * sizeof (char *));
  286.     }
  287.  
  288.   hostname_list[hostname_list_length] = savestring (name);
  289.   hostname_list[++hostname_list_length] = (char *)NULL;
  290.   hostname_list_needs_sorting++;
  291. }
  292.  
  293. /* After you have added some names, you should sort the list of names. */
  294. static void
  295. sort_hostname_list ()
  296. {
  297.   extern int qsort_string_compare ();
  298.   if (hostname_list_needs_sorting && hostname_list)
  299.     qsort (hostname_list, hostname_list_length,
  300.        sizeof (char *), qsort_string_compare);
  301.   hostname_list_needs_sorting = 0;
  302. }
  303.  
  304. #define cr_whitespace(c) ((c) == '\r' || (c) == '\n' || whitespace(c))
  305.  
  306. static void
  307. snarf_hosts_from_file (filename)
  308.      char *filename;
  309. {
  310.   FILE *file = fopen (filename, "r");
  311.   char *temp, buffer[256], name[256];
  312.   register int i, start;
  313.  
  314.   if (!file)
  315.     return;
  316.  
  317.   while (temp = fgets (buffer, 255, file))
  318.     {
  319.       /* Skip to first character. */
  320.       for (i = 0; buffer[i] && cr_whitespace (buffer[i]); i++);
  321.  
  322.       /* If comment, ignore. */
  323.       if (buffer[i] == '#')
  324.     continue;
  325.  
  326.       /* If `preprocessor' directive, do the include. */
  327.       if (strncmp (&buffer[i], "$include ", 9) == 0)
  328.     {
  329.       char *includefile = &buffer[i + 9];
  330.       char *t;
  331.  
  332.       /* Find start of filename. */
  333.       while (*includefile && whitespace (*includefile))
  334.         includefile++;
  335.  
  336.       t = includefile;
  337.  
  338.       /* Find end of filename. */
  339.       while (*t && !cr_whitespace (*t))
  340.         t++;
  341.  
  342.       *t = '\0';
  343.  
  344.       snarf_hosts_from_file (includefile);
  345.       continue;
  346.     }
  347.  
  348.       /* Skip internet address. */
  349.       for (; buffer[i] && !cr_whitespace (buffer[i]); i++);
  350.  
  351.       /* Gobble up names.  Each name is separated with whitespace. */
  352.       while (buffer[i] && buffer[i] != '#')
  353.     {
  354.       for (; i && cr_whitespace (buffer[i]); i++);
  355.       if (buffer[i] ==  '#')
  356.         continue;
  357.       for (start = i; buffer[i] && !cr_whitespace (buffer[i]); i++);
  358.       if ((i - start) == 0)
  359.         continue;
  360.       strncpy (name, buffer + start, i - start);
  361.       name[i - start] = '\0';
  362.       add_host_name (name);
  363.     }
  364.     }
  365.   fclose (file);
  366. }
  367.  
  368. /* Return a NULL terminated list of hostnames which begin with TEXT.
  369.    Initialize the hostname list the first time if neccessary.
  370.    The array is malloc ()'ed, but not the individual strings. */
  371. static char **
  372. hostnames_matching (text)
  373.      char *text;
  374. {
  375.   register int i, len = strlen (text);
  376.   register int begin, end;
  377.   int last_search = -1;
  378.   char **result = (char **)NULL;
  379.  
  380.   if (!hostname_list_initialized)
  381.     {
  382.       initialize_hostname_list ();
  383.  
  384.       if (!hostname_list_initialized)
  385.     return ((char **)NULL);
  386.     }
  387.  
  388.   sort_hostname_list ();
  389.  
  390.   /* The list is sorted.  Do a binary search on it for the first character
  391.      in TEXT, and then grovel the names of interest. */
  392.   begin = 0; end = hostname_list_length;
  393.  
  394.   /* Special case.  If TEXT consists of nothing, then the whole list is
  395.      what is desired. */
  396.   if (!*text)
  397.     {
  398.       result = (char **)xmalloc ((1 + hostname_list_length) * sizeof (char *));
  399.       for (i = 0; i < hostname_list_length; i++)
  400.     result[i] = hostname_list[i];
  401.       result[i] = (char *)NULL;
  402.       return (result);
  403.     }
  404.  
  405.   /* Scan until found, or failure. */
  406.   while (end != begin)
  407.     {
  408.       int r = 0;
  409.  
  410.       i = ((end - begin) / 2) + begin;
  411.       if (i == last_search)
  412.     break;
  413.  
  414.       if (hostname_list[i] &&
  415.       (r = strncmp (hostname_list[i], text, len)) == 0)
  416.     {
  417.       while (strncmp (hostname_list[i], text, len) == 0 && i) i--;
  418.       if (strncmp (hostname_list[i], text, len) != 0) i++;
  419.  
  420.       begin = i;
  421.       while (hostname_list[i] &&
  422.          strncmp (hostname_list[i], text, len) == 0) i++;
  423.       end = i;
  424.  
  425.       result = (char **)xmalloc ((1 + (end - begin)) * sizeof (char *));
  426.       for (i = 0; i + begin < end; i++)
  427.         result[i] = hostname_list[begin + i];
  428.       result[i] = (char *)NULL;
  429.       return (result);
  430.     }
  431.  
  432.       last_search = i;
  433.  
  434.       if (r < 0)
  435.     begin = i;
  436.       else
  437.     end = i;
  438.     }
  439.   return ((char **)NULL);
  440. }
  441. #endif 
  442.  
  443. /* This is a K*rn shell style insert-last-arg function.  The
  444.    difference is that Bash puts stuff into the history file before
  445.    expansion and file name generation, so we deal with exactly what the
  446.    user typed.  Those wanting the other behavior, at least for the last
  447.    arg, can use `$_'.  This also `knows' about how rl_yank_nth_arg treats
  448.    `$'. */
  449. static void
  450. insert_last_arg (count, c)
  451.      int count, c;
  452. {
  453.   extern int rl_explicit_arg;
  454.  
  455.   if (rl_explicit_arg)
  456.     rl_yank_nth_arg (count, c);
  457.   else
  458.     rl_yank_nth_arg ('$', c);
  459. }
  460.  
  461. /* The equivalent of the K*rn shell C-o operate-and-get-next-history-line
  462.    editing command. */
  463. static int saved_history_line_to_use = 0;
  464.  
  465. static void
  466. set_saved_history ()
  467. {
  468.   HIST_ENTRY *h;
  469.  
  470.   if (saved_history_line_to_use)
  471.     {
  472.       if (history_set_pos (saved_history_line_to_use))
  473.     {
  474.       h = current_history ();
  475.       if (h)
  476.         {
  477.           rl_insert_text (h->line);
  478.           /*
  479.            * Get rid of any undo list created by the previous insert,
  480.            * so the line won't totally be erased when the edits are
  481.            * undone (they will be normally, because this is a history
  482.            * line -- cf. readline.c: line 380 or so).
  483.            */
  484.           if (rl_undo_list)
  485.         {
  486.           free_undo_list ();
  487.           rl_undo_list = (UNDO_LIST *)NULL;
  488.         }
  489.         }
  490.     }
  491.     }
  492.   saved_history_line_to_use = 0;
  493.   rl_startup_hook = (Function *)NULL;
  494. }  
  495.  
  496. static void
  497. operate_and_get_next (count, c)
  498.      int count, c;
  499. {
  500.   int where;
  501.   extern int history_stifled, history_length, max_input_history;
  502.  
  503.   /* Accept the current line. */
  504.   rl_newline ();    
  505.  
  506.   /* Find the current line, and find the next line to use. */
  507.   where = where_history ();
  508.  
  509.   if (history_stifled && (history_length >= max_input_history))
  510.     saved_history_line_to_use = where;
  511.   else
  512.     saved_history_line_to_use = where + 1;
  513.  
  514.   rl_startup_hook = (Function *)set_saved_history;
  515. }
  516.  
  517. /* **************************************************************** */
  518. /*                                    */
  519. /*            How To Do Shell Completion            */
  520. /*                                    */
  521. /* **************************************************************** */
  522.  
  523. /* Do some completion on TEXT.  The indices of TEXT in RL_LINE_BUFFER are
  524.    at START and END.  Return an array of matches, or NULL if none. */
  525. static char **
  526. attempt_shell_completion (text, start, end)
  527.      char *text;
  528.      int start, end;
  529. {
  530.   int in_command_position = 0;
  531.   char **matches = (char **)NULL;
  532.   char *command_separator_chars = ";|&{(";
  533.  
  534.   /* Determine if this could be a command word. */
  535.   if (start == 0)
  536.     in_command_position++;
  537.   else
  538.     {
  539.       register int ti = start - 1;
  540.  
  541.       while (whitespace (rl_line_buffer[ti]) && ti > -1)
  542.     ti--;
  543.  
  544.       if (ti < 0)
  545.     in_command_position++;
  546.       else
  547.     {
  548.       if (member (rl_line_buffer[ti], command_separator_chars) ||
  549.           member (*text, command_separator_chars))
  550.         in_command_position++;
  551.     }
  552.     }
  553.  
  554.   /* Variable name? */
  555.   if (*text == '$')
  556.     {
  557.       matches = completion_matches (text, variable_completion_function);
  558.     }
  559.  
  560.   /* If the word starts in `~', and there is no slash in the word, then
  561.      try completing this word as a username. */
  562.   if (!matches && *text == '~' && !index (text, '/'))
  563.     {
  564.       matches = completion_matches (text, username_completion_function);
  565.     }
  566.  
  567.   /* Another one.  Why not?  If the word starts in '@', then look through
  568.      the world of known hostnames for completion first. */
  569. /**
  570.  ** (sjk)++ Remove hostname/mail references on the Atari ST.
  571.  **/
  572. #if !defined(atarist)
  573.   if (!matches && *text == '@')
  574.     {
  575.       matches = completion_matches (text, hostname_completion_function);
  576.     }
  577. #endif 
  578.  
  579.   /* And last, (but not least) if this word is in a command position, then
  580.      complete over possible command names, including aliases, functions,
  581.      and command names. */
  582.  
  583.   if (!matches && in_command_position)
  584.     {
  585.       int text_offset = 0;
  586.  
  587.       if (start && member (*text, command_separator_chars))
  588.     text_offset++, start++;
  589.  
  590.       if (*text != '/')
  591.     matches = completion_matches (&text[text_offset],
  592.                       command_word_completion_function);
  593.     }
  594.   return (matches);
  595. }
  596.  
  597. /* This is the function to call when the word to complete is at the start
  598.    of a line.  It grovels $PATH, looking for commands that match.  It also
  599.    scans for aliases, function names, and the shell_builtin table. */
  600. static char *
  601. command_word_completion_function (hint_text, state)
  602.      char *hint_text;
  603.      int state;
  604. {
  605.   static char *hint = (char *)NULL;
  606.   static char *path = (char *)NULL;
  607.   static char *val = (char *)NULL;
  608.   static char *filename_hint = (char *)NULL;
  609.   char *extract_colon_unit ();
  610.   static int path_index, hint_len, istate;
  611.   static int mapping_over, local_index;
  612.   static SHELL_VAR **varlist = (SHELL_VAR **)NULL;
  613.   extern SHELL_VAR **all_visible_functions ();
  614.  
  615.   /* We have to map over the possibilities for command words.  If we have
  616.      no state, then make one just for that purpose. */
  617.  
  618.   if (!state)
  619.     {
  620.       if (hint)
  621.     free (hint);
  622.  
  623.       path = get_string_value ("PATH");
  624.       path_index = 0;
  625.  
  626.       hint = savestring (hint_text);
  627.       hint_len = strlen (hint);
  628.  
  629.       mapping_over = 0;
  630.       val = (char *)NULL;
  631.  
  632.       /* Initialize the variables for each type of command word. */
  633.       local_index = 0;
  634.  
  635.       if (varlist)
  636.     free (varlist);
  637.  
  638.       varlist = all_visible_functions ();
  639.     }
  640.  
  641.   /* mapping_over says what we are currently hacking.  Note that every case
  642.      in this list must fall through when there are no more possibilities. */
  643.  
  644.   switch (mapping_over)
  645.     {
  646.     case 0:            /* Aliases come first. */
  647. #if defined (ALIAS)
  648.       while (aliases && aliases[local_index])
  649.     {
  650.       register char *alias;
  651.  
  652.       alias = aliases[local_index++]->name;
  653.  
  654.       if (strncmp (alias, hint, hint_len) == 0)
  655.         return (savestring (alias));
  656.     }
  657. #endif /* ALIAS */
  658.       local_index = 0;
  659.       mapping_over++;
  660.  
  661.     case 1:            /* Then function names. */
  662.       while (varlist && varlist[local_index])
  663.     {
  664.       register char *varname;
  665.  
  666.       varname = varlist[local_index++]->name;
  667.  
  668.       if (strncmp (varname, hint, hint_len) == 0)
  669.         return (savestring (varname));
  670.     }
  671.       local_index = 0;
  672.       mapping_over++;
  673.  
  674.     case 2:            /* Then shell builtins. */
  675.       while (shell_builtins[local_index].function)
  676.     {
  677.       register char *builtin_name;
  678.  
  679.       if (!shell_builtins[local_index].enabled)
  680.         {
  681.           local_index++;
  682.           continue;
  683.         }
  684.  
  685.       builtin_name = shell_builtins[local_index++].name;
  686.  
  687.       if (strncmp (builtin_name, hint, hint_len) == 0)
  688.         return (savestring (builtin_name));
  689.     }
  690.       local_index = 0;
  691.       mapping_over++;
  692.     }
  693.  
  694.   /* Repeatedly call filename_completion_function while we have
  695.      members of PATH left.  Question:  should we stat each file?
  696.      Answer: we call executable_file () on each file. */
  697.  outer:
  698.  
  699.   istate = (val != (char *)NULL);
  700.  
  701.   if (!istate)
  702.     {
  703.       char *current_path;
  704.  
  705.       /* Get the next directory from the path.  If there is none, then we
  706.      are all done. */
  707.       if (!path ||
  708.       !path[path_index] ||
  709.       !(current_path = extract_colon_unit (path, &path_index)))
  710.     return ((char *)NULL);
  711.  
  712.       if (!*current_path)
  713.     {
  714.       free (current_path);
  715.       current_path = savestring (".");
  716.     }
  717.  
  718.       if (filename_hint)
  719.     free (filename_hint);
  720.  
  721.       filename_hint =
  722.     (char *)xmalloc (2 + strlen (current_path)
  723.              + strlen (hint));
  724.       sprintf (filename_hint, "%s/%s", current_path, hint);
  725.  
  726.       free (current_path);
  727.     }
  728.  
  729.  inner:
  730.   val = filename_completion_function (filename_hint, istate);
  731.   istate = 1;
  732.  
  733.   if (!val)
  734.     {
  735.       goto outer;
  736.     }
  737.   else
  738.     {
  739.       char *rindex (), *temp = rindex (val, '/');
  740.       temp++;
  741.       if ((strncmp (hint, temp, hint_len) == 0) && executable_file (val))
  742.     {
  743.       temp = (savestring (temp));
  744.       free (val);
  745.       val = "";    /* So it won't be NULL. */
  746.       return (temp);
  747.     }
  748.       else
  749.     {
  750.       free (val);
  751.       goto inner;
  752.     }
  753.     }
  754. }
  755.  
  756. /* Okay, now we write the entry_function for variable completion. */
  757. static char *
  758. variable_completion_function (text, state)
  759.      int state;
  760.      char *text;
  761. {
  762.   register SHELL_VAR *var = (SHELL_VAR *)NULL;
  763.   static SHELL_VAR **varlist = (SHELL_VAR **)NULL;
  764.   static int varlist_index;
  765.   static char *varname = (char *)NULL;
  766.   static int namelen;
  767.   static int first_char, first_char_loc;
  768.  
  769.   extern SHELL_VAR **all_visible_variables ();
  770.  
  771.   if (!state)
  772.     {
  773.       if (varname)
  774.     free (varname);
  775.  
  776.       first_char_loc = 0;
  777.       first_char = text[0];
  778.  
  779.       if (first_char == '$')
  780.     first_char_loc++;
  781.  
  782.       varname = savestring (&text[first_char_loc]);
  783.  
  784.       namelen = strlen (varname);
  785.       if (varlist)
  786.     free (varlist);
  787.       varlist = all_visible_variables ();
  788.       varlist_index = 0;
  789.     }
  790.  
  791.   while (varlist && varlist[varlist_index])
  792.     {
  793.       var = varlist[varlist_index];
  794.  
  795.       /* Compare.  You can't do better than Zayre.  No text is also
  796.      a match.  */
  797.       if (!*varname || (strncmp (varname, var->name, namelen) == 0))
  798.     break;
  799.       varlist_index++;
  800.     }
  801.  
  802.   if (!varlist || !varlist[varlist_index])
  803.     {
  804.       return ((char *)NULL);
  805.     }
  806.   else
  807.     {
  808.       char *value = (char *)xmalloc (2 + strlen (var->name));
  809.  
  810.       if (first_char_loc)
  811.     *value = first_char;
  812.  
  813.       strcpy (&value[first_char_loc], var->name);
  814.  
  815.       varlist_index++;
  816.       return (value);
  817.     }
  818. }
  819.  
  820. /**
  821.  ** (sjk)++ Remove hostname/mail references on the Atari ST.
  822.  **/
  823. #if !defined(atarist)
  824. /* How about a completion function for hostnames? */
  825. static char *
  826. hostname_completion_function (text, state)
  827.      int state;
  828.      char *text;
  829. {
  830.   static char **list = (char **)NULL;
  831.   static int list_index = 0;
  832.   static int first_char, first_char_loc;
  833.  
  834.   /* If we don't have any state, make some. */
  835.   if (!state)
  836.     {
  837.       char **hostnames_matching ();
  838.  
  839.       if (list)
  840.     free (list);
  841.  
  842.       list = (char **)NULL;
  843.  
  844.       first_char_loc = 0;
  845.       first_char = *text;
  846.  
  847.       if (first_char == '@')
  848.     first_char_loc++;
  849.  
  850.       list = hostnames_matching (&text[first_char_loc]);
  851.       list_index = 0;
  852.     }
  853.  
  854.   if (list && list[list_index])
  855.     {
  856.       char *t = (char *)xmalloc (2 + strlen (list[list_index]));
  857.  
  858.       *t = first_char;
  859.       strcpy (t + first_char_loc, list[list_index]);
  860.       list_index++;
  861.       return (t);
  862.     }
  863.   else
  864.     return ((char *)NULL);
  865. }
  866. #endif 
  867.  
  868. /* History and alias expand the line.  But maybe do more?  This
  869.    is a test to see what users like.  Do expand_string on the string. */
  870. static void
  871. shell_expand_line (ignore)
  872.      int ignore;
  873. {
  874.   char *pre_process_line (), *new_line;
  875.  
  876.   new_line = pre_process_line (rl_line_buffer, 0, 0);
  877.  
  878. #if defined (ALIAS)
  879.   if (new_line)
  880.     {
  881.       char *alias_expand (), *alias_line;
  882.  
  883.       alias_line = alias_expand (new_line);
  884.       free (new_line);
  885.       new_line = alias_line;
  886.     }
  887. #endif /* ALIAS */
  888.  
  889.   if (new_line)
  890.     {
  891.       int old_point = rl_point;
  892.       int at_end = rl_point == rl_end;
  893.  
  894.       /* If the line was history and alias expanded, then make that
  895.      be one thing to undo. */
  896.  
  897.       if (strcmp (new_line, rl_line_buffer) != 0)
  898.     {
  899.       rl_point = rl_end;
  900.  
  901.       rl_add_undo (UNDO_BEGIN, 0, 0, 0);
  902.       rl_kill_text (0, rl_point);
  903.       rl_point = rl_end = 0;
  904.       rl_insert_text (new_line);
  905.       rl_add_undo (UNDO_END, 0, 0, 0);
  906.     }
  907.  
  908.       free (new_line);
  909.  
  910.       /* If there is variable expansion to perform, do that as a separate
  911.      operation to be undone. */
  912.       {
  913.     extern char *string_list ();
  914.     extern WORD_LIST *expand_string ();
  915.     WORD_LIST *expanded_string;
  916.     char *string_list ();
  917.  
  918.     expanded_string = expand_string (rl_line_buffer, 0);
  919.     if (!expanded_string)
  920.       new_line = savestring ("");
  921.     else
  922.       {
  923.         new_line = string_list (expanded_string);
  924.         dispose_words (expanded_string);
  925.       }
  926.  
  927.       if (strcmp (new_line, rl_line_buffer) != 0)
  928.     {
  929.       rl_add_undo (UNDO_BEGIN, 0, 0 ,0);
  930.       rl_kill_text (0, rl_end);
  931.       rl_point = rl_end = 0;
  932.       rl_insert_text (new_line);
  933.       rl_add_undo (UNDO_END, 0, 0, 0);
  934.     }
  935.  
  936.       free (new_line);
  937.  
  938.       /* Place rl_point where we think it should go. */
  939.       if (at_end)
  940.     rl_point = rl_end;
  941.       else if (old_point < rl_end)
  942.     {
  943.       rl_point = old_point;
  944.       if (!whitespace (rl_line_buffer[rl_point]))
  945.         rl_forward_word (1);
  946.     }
  947.       }
  948.     }
  949.   else
  950.     {
  951.       /* There was an error in expansion.  Let the preprocessor print
  952.      the error here.  Note that we know that pre_process_line ()
  953.      will return NULL, since it just did. */
  954.       fprintf (rl_outstream, "\n\r");
  955.       pre_process_line (rl_line_buffer, 1, 0);
  956.       rl_forced_update_display ();
  957.     }
  958. }
  959.  
  960. /* Filename completion ignore.  Emulates the "fignore" facility of
  961.    tcsh.  If FIGNORE is set, then don't match files with the
  962.    given suffixes.  If only one of the possabilities has an acceptable
  963.    suffix, delete the others, else just return and let the completer
  964.    signal an error.  It is called by the completer when real
  965.    completions are done on filenames by the completer's internal
  966.    function, not for completion lists (M-?) and not on "other"
  967.    completion types, such as hostnames or commands.
  968.  
  969.    It is passed a NULL-terminated array of (char *)'s that must be
  970.    free()'d if they are deleted.  The first element (names[0]) is the
  971.    least-common-denominator string of the matching patterns (i.e.
  972.    u<TAB> produces names[0] = "und", names[1] = "under.c", names[2] =
  973.    "undun.c", name[3] = NULL).  */
  974.  
  975. struct ign {
  976.   char *val;
  977.   int len;
  978. };
  979.  
  980. static struct ign *ignores;    /* Store the ignore strings here */
  981. static int num_ignores;        /* How many are there? */
  982. static char *last_fignore;    /* Last value of fignore - cached for speed */
  983. extern char *extract_colon_unit (), *get_string_value ();
  984.  
  985. static void
  986. setup_ignore_patterns ()
  987. {
  988.   int numitems, maxitems, ptr;
  989.   char *colon_bit;
  990.   struct ign *p;
  991.   
  992.   char *this_fignore = get_string_value ("FIGNORE");
  993.  
  994.   /* If nothing has changed then just exit now. */
  995.   if (this_fignore &&
  996.       last_fignore && 
  997.       strcmp (this_fignore, last_fignore) == 0 ||
  998.       (!this_fignore && !last_fignore))
  999.     {
  1000.       return;
  1001.     }
  1002.  
  1003.   /* Oops.  FIGNORE has changed.  Re-parse it. */
  1004.   num_ignores = 0;
  1005.  
  1006.   if (ignores)
  1007.     {
  1008.       for (p = ignores; p->val; p++) free(p->val);
  1009.       free (ignores);
  1010.       ignores = (struct ign*)NULL;
  1011.     }
  1012.  
  1013.   if (last_fignore)
  1014.     free (last_fignore);
  1015.  
  1016.   last_fignore = savestring (this_fignore);
  1017.   
  1018.   if (!this_fignore)
  1019.     return;
  1020.  
  1021.   numitems = maxitems = ptr = 0;
  1022.  
  1023.   while (colon_bit = extract_colon_unit (this_fignore, &ptr))
  1024.     {
  1025.       if (numitems + 1 > maxitems)
  1026.     ignores = (struct ign *)
  1027.       xrealloc ((char *)ignores, (maxitems += 10) * sizeof (struct ign));
  1028.  
  1029.       ignores[numitems].val = colon_bit;
  1030.       ignores[numitems].len = strlen (colon_bit);
  1031.       numitems++;
  1032.     }
  1033.   ignores[numitems].val = NULL;
  1034.   num_ignores = numitems;
  1035. }
  1036.  
  1037. static int
  1038. name_is_acceptable (name)
  1039.      char *name;
  1040. {
  1041.   struct ign *p;
  1042.   int nlen = strlen (name);
  1043.  
  1044.   for (p = ignores; p->val; p++) 
  1045.     {
  1046.       if (nlen > p->len && p->len > 0 && 
  1047.       strcmp (p->val, &name[nlen - p->len]) == 0)
  1048.     return (0);
  1049.     }
  1050.  
  1051.   return (1);
  1052. }
  1053.  
  1054. static void
  1055. filename_completion_ignore (names)
  1056.      char **names;
  1057. {
  1058.   char **p;
  1059.   int idx;
  1060.  
  1061.   setup_ignore_patterns ();
  1062.  
  1063.   if (!num_ignores)
  1064.     return;
  1065.   
  1066.   for (p = names + 1, idx = -1; *p; p++)
  1067.     {
  1068.       if (name_is_acceptable (*p))
  1069.     {
  1070.       if (idx == -1)    /* First match found. */
  1071.         idx = p - names;
  1072.       else
  1073.         return;        /* Too many matches. */
  1074.     }
  1075.     }
  1076.   
  1077.   /* If none are acceptable then let the completer handle it. */
  1078.   if (idx == -1)
  1079.     return;
  1080.  
  1081.   /* Delete all non-matching elements. */
  1082.   free (names[0]); 
  1083.   for (p = names + 1; *p; p++)
  1084.     {
  1085.       if (idx == (p - names))
  1086.     names[0] = *p;
  1087.       else 
  1088.     free (*p);
  1089.  
  1090.       *p = NULL;
  1091.     }
  1092. }
  1093.  
  1094. /* If tilde_expand hasn't been able to expand the text, perhaps it
  1095.    is a special shell expansion.  We handle that here. */
  1096. static char *
  1097. bash_tilde_expand (text)
  1098.      char *text;
  1099. {
  1100.   char *result = (char *)NULL;
  1101.  
  1102.   if (strcmp (text, "-") == 0)
  1103.     result = get_string_value ("OLDPWD");
  1104.   else if (strcmp (text, "+") == 0)
  1105.     result = get_string_value ("PWD");
  1106.  
  1107.   if (result)
  1108.     result = savestring (result);
  1109.  
  1110.   return (result);
  1111. }
  1112.  
  1113. /* Handle symbolic link references while hacking completion. */
  1114. static void
  1115. bash_symbolic_link_hook (dirname)
  1116.      char **dirname;
  1117. {
  1118.   extern int follow_symbolic_links;
  1119.   char *make_absolute (), *temp_dirname;
  1120.  
  1121.   if (follow_symbolic_links && (strcmp (*dirname, ".") != 0))
  1122.     {
  1123.       temp_dirname = make_absolute (*dirname, get_working_directory (""));
  1124.  
  1125.       if (temp_dirname)
  1126.     {
  1127.       free (*dirname);
  1128.       *dirname = temp_dirname;
  1129.     }
  1130.     }
  1131. }
  1132.  
  1133. #if defined (SPECIFIC_COMPLETION_FUNCTIONS)
  1134. static void
  1135. bash_complete_username (ignore, ignore2)
  1136.      int ignore, ignore2;
  1137. {
  1138.   bash_complete_username_internal (TAB);
  1139. }
  1140.  
  1141. static void
  1142. bash_possible_username_completions (ignore, ignore2)
  1143.      int ignore, ignore2;
  1144. {
  1145.   bash_complete_username_internal ('?');
  1146. }
  1147.  
  1148. static void
  1149. bash_complete_username_internal (what_to_do)
  1150.      int what_to_do;
  1151. {
  1152.   bash_specific_completion
  1153.     (what_to_do, (Function *)username_completion_function);
  1154. }
  1155.  
  1156. static void
  1157. bash_complete_filename (ignore, ignore2)
  1158.      int ignore, ignore2;
  1159. {
  1160.   bash_complete_filename_internal (TAB);
  1161. }
  1162.  
  1163. static void
  1164. bash_possible_filename_completions (ignore, ignore2)
  1165.      int ignore, ignore2;
  1166. {
  1167.   bash_complete_filename_internal ('?');
  1168. }
  1169.  
  1170. static void
  1171. bash_complete_filename_internal (what_to_do)
  1172.      int what_to_do;
  1173. {
  1174.   Function  *orig_func;
  1175.   Function *orig_attempt_func;
  1176.   char *orig_rl_completer_word_break_characters;
  1177.   extern char *rl_completer_word_break_characters;
  1178.  
  1179.   orig_func = rl_completion_entry_function;
  1180.   orig_attempt_func = rl_attempted_completion_function;
  1181.   orig_rl_completer_word_break_characters = rl_completer_word_break_characters;
  1182.   rl_completion_entry_function = (Function *)filename_completion_function;
  1183.   rl_attempted_completion_function = (Function *)0x0;
  1184.   rl_completer_word_break_characters = " \t\n\"\'";
  1185.  
  1186.   rl_complete_internal (what_to_do);
  1187.  
  1188.   rl_completion_entry_function = orig_func;
  1189.   rl_attempted_completion_function = orig_attempt_func;
  1190.   rl_completer_word_break_characters = orig_rl_completer_word_break_characters;
  1191. }
  1192.  
  1193. /**
  1194.  ** (sjk)++ Remove hostname/mail references on the Atari ST.
  1195.  **/
  1196. #if !defined(atarist)
  1197. static void
  1198. bash_complete_hostname (ignore, ignore2)
  1199.      int ignore, ignore2;
  1200. {
  1201.   bash_complete_hostname_internal (TAB);
  1202. }
  1203.  
  1204. static void
  1205. bash_possible_hostname_completions (ignore, ignore2)
  1206.      int ignore, ignore2;
  1207. {
  1208.   bash_complete_hostname_internal ('?');
  1209. }
  1210. #endif 
  1211.  
  1212. static void
  1213. bash_complete_variable (ignore, ignore2)
  1214.      int ignore, ignore2;
  1215. {
  1216.   bash_complete_variable_internal (TAB);
  1217. }
  1218.  
  1219. static void
  1220. bash_possible_variable_completions (ignore, ignore2)
  1221.      int ignore, ignore2;
  1222. {
  1223.   bash_complete_variable_internal ('?');
  1224. }
  1225.  
  1226.  
  1227. static void
  1228. bash_complete_command (ignore, ignore2)
  1229.      int ignore, ignore2;
  1230. {
  1231.   bash_complete_command_internal (TAB);
  1232. }
  1233.  
  1234. static void
  1235. bash_possible_command_completions (ignore, ignore2)
  1236.      int ignore, ignore2;
  1237. {
  1238.   bash_complete_command_internal ('?');
  1239. }
  1240.  
  1241. /**
  1242.  ** (sjk)++ Remove hostname/mail references on the Atari ST.
  1243.  **/
  1244. #if !defined(atarist)
  1245. static void
  1246. bash_complete_hostname_internal (what_to_do)
  1247.      int what_to_do;
  1248. {
  1249.   bash_specific_completion
  1250.     (what_to_do, (Function *)hostname_completion_function);
  1251. }
  1252. #endif 
  1253.  
  1254. static void
  1255. bash_complete_variable_internal (what_to_do)
  1256.      int what_to_do;
  1257. {
  1258.   bash_specific_completion
  1259.     (what_to_do, (Function *)variable_completion_function);
  1260. }
  1261.  
  1262. static void
  1263. bash_complete_command_internal (what_to_do)
  1264.      int what_to_do;
  1265. {
  1266.   bash_specific_completion
  1267.     (what_to_do, (Function *)command_word_completion_function);
  1268. }
  1269.  
  1270. static void
  1271. bash_specific_completion (what_to_do, generator)
  1272.      int what_to_do;
  1273.      Function *generator;
  1274. {
  1275.   Function *orig_func;
  1276.   Function *orig_attempt_func;
  1277.  
  1278.   orig_func = rl_completion_entry_function;
  1279.   orig_attempt_func = rl_attempted_completion_function;
  1280.   rl_completion_entry_function = generator;
  1281.   rl_attempted_completion_function = (Function *)0x0;
  1282.  
  1283.   rl_complete_internal (what_to_do);
  1284.  
  1285.   rl_completion_entry_function = orig_func;
  1286.   rl_attempted_completion_function = orig_attempt_func;
  1287. }
  1288.  
  1289. #endif    /* SPECIFIC_COMPLETION_FUNCTIONS */
  1290.  
  1291.